#include "tool_mxml.h"

int tmxmlIsElement(mxml_node_t *Element, char const *String)
{
	char const *_String;

	_String = mxmlGetElement(Element);
	if (NULL != _String)
	{
		return 0 == strcmp(_String, String);
	}
	else
	{
		return 0;
	}
}

void tmxmlElementReadChildText(mxml_node_t *Element, char *Buf)
{
	char _String[STRING_BUF_SIZE];
	mxml_node_t *_Child;

	memset(_String, 0, sizeof _String);
	_Child = mxmlGetFirstChild(Element);
	for (; _Child != NULL; _Child = mxmlWalkNext(_Child, Element, MXML_NO_DESCEND))
	{
		if (MXML_TEXT == mxmlGetType(_Child))
		{
			sprintf(_String, "%s %s", _String, mxmlGetText(_Child, NULL));
		}
	}
	strcpy(Buf, _String + 1);
}

int tmxmlElementReadChildInt(mxml_node_t *Element)
{
	char _String[128];

	memset(_String, 0, sizeof _String);
	tmxmlElementReadChildText(Element, _String);
	return atoi(_String);
}

float tmxmlElementReadChildFloat(mxml_node_t *Element)
{
	char _String[128];

	memset(_String, 0, sizeof _String);
	tmxmlElementReadChildText(Element, _String);
	return atof(_String);
}

void tmxmlReadStringTable(mxml_node_t *Bouy, std::vector<std::string> *Table, char const *Key)
{
	mxml_node_t *_SubBouy;
	char _Buf[128];

	_SubBouy = mxmlGetFirstChild(Bouy);
	for (; NULL != _SubBouy; _SubBouy = mxmlWalkNext(_SubBouy, Bouy, MXML_NO_DESCEND))
	{
		if (tmxmlIsElement(_SubBouy, Key))
		{
			memset(_Buf, 0, sizeof _Buf);
			tmxmlElementReadChildText(_SubBouy, _Buf);
			Table->push_back(std::string(_Buf));
		}
	}
}

void tmxmlReadIntTable(mxml_node_t *Bouy, std::vector<int> *Table, char const *Key)
{
	mxml_node_t *_SubBouy;

	_SubBouy = mxmlGetFirstChild(Bouy);
	for (; NULL != _SubBouy; _SubBouy = mxmlWalkNext(_SubBouy, Bouy, MXML_NO_DESCEND))
	{
		if (tmxmlIsElement(_SubBouy, Key))
		{
			Table->push_back(tmxmlElementReadChildInt(_SubBouy));
		}
	}
}

void tmxmlReadFloatTable(mxml_node_t *Bouy, std::vector<float> *Table, char const *Key)
{
	mxml_node_t *_SubBouy;

	_SubBouy = mxmlGetFirstChild(Bouy);
	for (; NULL != _SubBouy; _SubBouy = mxmlWalkNext(_SubBouy, Bouy, MXML_NO_DESCEND))
	{
		if (tmxmlIsElement(_SubBouy, Key))
		{
			Table->push_back(tmxmlElementReadChildFloat(_SubBouy));
		}
	}
}

void tmxmlReadCGPointTable(mxml_node_t *Bouy, std::vector<CGPoint> *Table)
{
	mxml_node_t *_SubBouy;
	CGPoint _Point;

	_SubBouy = mxmlGetFirstChild(Bouy);
	for (; NULL != _SubBouy; _SubBouy = mxmlWalkNext(_SubBouy, Bouy, MXML_NO_DESCEND))
	{
		if (tmxmlIsElement(_SubBouy, "point"))
		{
			uiLoadPointFromXML(_SubBouy, &_Point);
			Table->push_back(_Point);
		}
	}
}

void tmxmlReadIntArray(mxml_node_t *Bouy, int *Array, char const *Key)
{
	int _Index;
	mxml_node_t *_SubBouy;

	_Index = 0;
	_SubBouy = mxmlGetFirstChild(Bouy);
	for (; NULL != _SubBouy; _SubBouy = mxmlWalkNext(_SubBouy, Bouy, MXML_NO_DESCEND))
	{
		if (tmxmlIsElement(_SubBouy, Key))
		{
			Array[_Index++] = tmxmlElementReadChildInt(_SubBouy);
		}
	}
}

void tmxmlNodeAddIntChild(mxml_node_t *Element, char const *Key, int Data)
{
	mxml_node_t *_Child;

	_Child = mxmlNewElement(Element, Key);
	mxmlNewInteger(_Child, Data);
}

void tmxmlNodeAddIntArray(mxml_node_t *Bouy, int *Array, int Size, char const *Key, char const *SubKey)
{
	int i;
	mxml_node_t *_Child;

	_Child = mxmlNewElement(Bouy, Key);
	for (i = 0; i < Size; i++)
	{
		tmxmlNodeAddIntChild(_Child, SubKey, Array[i]);
	}
}

char const *tmxmlCallBackXmlWhitespace(mxml_node_t *Node, int Where)
{
	int i;
	int _ParentCount;
	mxml_node_t *_ChildNode;
	mxml_type_t _Type, _ChildType;
	char const *_Name;
	static char _String[128];

	_Name = mxmlGetElement(Node);

	if (0 == strcmp(_Name, "?xml version=\"1.0\" encoding=\"utf-8\"?"))
	{
		if (MXML_WS_AFTER_OPEN == Where)
		{
			return "\n";
		}
		else
		{
			return NULL;
		}
	}
	else
	{
		_Type = mxmlGetType(Node);
		_ChildNode = mxmlGetFirstChild(Node);
		if (NULL != _ChildNode)
		{
			_ChildType = mxmlGetType(_ChildNode);
		}
		else
		{
			_ChildType = MXML_IGNORE;
		}
		memset(_String, 0, sizeof _String);
		_ParentCount = tmxmlNodeGetParentCount(Node);
		if (MXML_ELEMENT == _Type)
		{
			switch (Where)
			{
			case MXML_WS_BEFORE_OPEN:
				if (0 == _ParentCount)
				{
					return "\n";
				}
				else
				{
					for (i = 0; i < _ParentCount; ++i)
					{
						sprintf(_String, "%s\t", _String);
					}
					return _String;
				}
			case MXML_WS_AFTER_OPEN:
				if (MXML_ELEMENT == _ChildType)
				{
					return "\n";
				}
				else
				{
					return NULL;
				}
			case MXML_WS_BEFORE_CLOSE:
				if (MXML_ELEMENT == _ChildType)
				{
					for (i = 0; i < _ParentCount; ++i)
					{
						sprintf(_String, "%s\t", _String);
					}
					return _String;
				}
				else
				{
					return NULL;
				}
			case MXML_WS_AFTER_CLOSE:
				if (MXML_ELEMENT == _Type)
				{
					return "\n";
				}
				else
				{
					return NULL;
				}
			}
		}
		else
		{
			return NULL;
		}
	}
	return NULL;
}

int tmxmlNodeGetParentCount(mxml_node_t *Node)
{
	int _Ret;
	mxml_node_t *_Node;

	_Node = mxmlGetParent(Node);
	_Ret = 0;
	while (NULL != _Node)
	{
		_Node = mxmlGetParent(_Node);
		_Ret++;
	}
	_Ret--; /*do not include parent "?xml version="1.0" encoding="utf-8"?"*/
	return _Ret;
}